/**
 * 1.数据类型
 * String Number Boolean Undefined Null Object Symbol
 * 
 * 2.存储方式
 * 值类型和引用类型
 * 值类型 特点：数据分块存储　互不干扰
 * 引用类型 特点：存的是地址
 * 
 * 3.typeof运算符
 * 用来判断数据类型
 */
var a = 100
var b = a
a = 200
console.log(b)      //100   因为b存的是100本身，所以改变a的值，不会影响b

typeof undefined    //undefined
typeof null         //object        *******************这个要特别注意****************************
typeof {}           //object
typeof []           //object

typeof 'abc'        //string
typeof 123          //number
typeof true         //boolean
typeof console.log     //function
typeof console.log()     //undefined

// PS：要注意typeof null是object， typeof的返回值是字符串，且这个字符串是全小写
typeof typeof null      //string        因为typeof null 返回字符串object，所以第二次为typeof 'object'  所以返回字符串string
console.log(typeof typeof null)       //string
　　　
// ---------------------------------------------------------------------------------------------------------------------
/**
 * 4.类型转换
 * String转Number
 *  一元+
 *  减0
 *  除1
 *  乘1
 *  使用Number函数
 *  使用parseInt,parseFloat函数
 * 
 * 任意类型转String
 *  拼接空串：xxx + ''          记住这个，常用
 *  使用String函数：String(xxx)
 */
// *************使用一元+         记住这个，常用
var strNum = '123'
var num = +strNum           //通过一元 + 符号强转，注意，只能转纯数字字符串
strNum = '012'
strNum = '0.1'
strNum = '000'
num = +strNum 
console.log(typeof num,num)     //number  12 

strNum = '0ab'
num = +strNum 
console.log(typeof num,num)     //number  NaN 

// ***********使用-，/，*
strNum = '123'      
// num = strNum - 0             //同样只能转纯数字的字符串
num = strNum / 1
// num = strNum * 1
num = '000' - 0                   //number 0
num = '0ab' - 0                  //number NaN
console.log(typeof num,num)     //number 123

// ************使用天生的Number函数
strNum = '123'                  //同样只能转纯数字的字符串
num = Number(strNum)
console.log(typeof num,num)     //number 123

// ************使用天生的parseInt，parseFloat函数
strNum = '123'                  //可以转数字开头的字符串，直到第一个非数字的字符串为止(包括.)
strNum = '123ab'                  
strNum = '1.23ab'               //number 1     
strNum = '01.23ab'              //number 1   
num = parseInt(strNum)
console.log(typeof num,num)     //number 123

strNum = '123'                  //可以转数字开头的字符串，直到第一个非数字的字符串为止(不包括.)
strNum = '123ab'                  
strNum = '1.23ab'               //number 1.23     
strNum = '01.23ab'              //number 1.23   
num = parseFloat(strNum)
console.log(typeof num,num)     //number 123

// ---------------------------------------------------------------------------------------------------------------------
/**
 * String转Boolean
 *  !!                      常用，记住
 *  使用Boolean函数
 */
// ************使用2次非，!!
var str = '123'
str = ' '                                     //boolean true
str = ''                                      //boolean false
var strBoolean = !!str
console.log(typeof strBoolean,strBoolean)     //boolean true
// 结论，除了空串转Boolean是false，其余都是true

// ************使用Boolean函数
var str = '123'
str = ' '                                     //boolean true
str = ''                                      //boolean false
var strBoolean = Boolean(str)
console.log(typeof strBoolean,strBoolean)     //boolean true

// ---------------------------------------------------------------------------------------------------------------------
/**
 * Number转Boolean
 *  !!
 *  使用Boolean函数
 * 
 * Boolean转Number
 *  +,-0,/1,*1          一元正，减0，除1，乘1
 *  使用Number函数
 *  
 * 
 */
var num = 1
var numBoolean = !!num
console.log(typeof numBoolean,numBoolean)     //boolean true
// 结论：只有0是false，其余都是true

var flag = true
var flayNum = +flag 
// flayNum = flag - 0
flayNum = Number(flag)
console.log(typeof flayNum,flayNum)           //number 1
// 结论：布尔值转数字，true为1，false为0

// ---------------------------------------------------------------------------------------------------------------------
/**
 * 这个用的不多，Undefined和Null是可以转Number的
 */
var test = undefined
var test1 = null
var result = test - 0
var result1 = test1 - 0
console.log(result,result1)         //NaN   0
console.log(Number(undefined))      //NaN
console.log(Number(null))           //0
console.log(String(undefined))      //undefined
console.log(String(null))           //null
console.log(Boolean(undefined))      //false
console.log(Boolean(null))           //false
console.log(!!null)                  //false
// 结论：null转Number为0，undefined为NaN，，，null和undefined转Boolean都是false

// var num = 123
// var test = new Number(num)
// test.a = 1
// console.log('123'.length)
// console.log(num,test.a,test)

// ---------------------------------------------------------------------------------------------------------------------
/**
 * 5.何时使用===？何时使用==？ 知识点:强制类型转换
 * 区别=，==，===，这3个的含义
 * = ：赋值，把右边的东西给左边
 * == ：比较，左边和右边是否相等
 * === ：比较，左边和右边是否全等
 */
console.log(1=='1')        //true
console.log(1==1)         //true
console.log(1==='1')     //false
console.log(0==undefined)   //false
console.log(0==false)   //true
console.log(0==null)   //false            
console.log(0===null)   //false
console.log(null==undefined)   //true     特别注意，null和undefined是相等，但是不全等
console.log(null===undefined)   //false
// 特别注意，虽然null转数字之后为0，但是却不和0相等，只需记一个结论，，，null只和undefined相等，但不全等


// ---------------------------------------------------------------------------------------------------------------------
/**
 * 6.流程控制
 * if-else      拓展if-elseif-else
 * for循环
 * switch
 * &&与运算
 * ||或运算
 * !非运算
 * ？：三目运算
 */
if(true){
  //do your things
}else{
  //do your things
}

for(var i=0;i<10;i++){
  //do your things,,,这里面的代码会运行10次，直到i>=10才跳出循环，如果想提前跳出循环，要使用break
}
for(var i=0;i<10;i++){
  if(i==5){
    continue
  }else if(i==6){
    break
  }else{
    console.log(i)    //0 1 2 3 4
  }
}

var result = 1 && 0
var result4 = 0 && 1
var result2 = 5 == 4 && true
var result3 = null == undefined && 1+1
var result5 =  1+1 && null == undefined
console.log(result,result4,result2,result3,result5)     //0 0 false 2 true
// 结论: &&操作如果左边的判断为true，那么直接返回右边的值，如果左边的判断为false，那么直接返回左边的值,注意返回的是值，而不是这个值所对应的布尔值

var result = 1 || 0
var result4 = 0 || 1
var result2 = 5 == 4 || true
var result3 = null == undefined || 1+1
var result5 =  1+1 || null == undefined
console.log(result,result4,result2,result3,result5)     //1 1 true true 2
// 结论: ||操作如果左边的判断为true，那么直接返回左边的值，如果左边的判断为false，那么直接返回右边的值,注意返回的是值，而不是这个值所对应的布尔值

var xxx = !0
var xxx1 = !1
console.log(xxx,xxx1)   //true false    !操作(取反操作)，结果肯定是一个布尔，true/false

var yyy = true?1:0      //最简单的三目运算，
var yyy2 = 1+2+3-3-2-1?'如果？左边的表达式布尔为ture就返回我':'*****如果？左边的表达式布尔为false就返回我******'
console.log(yyy,yyy2)   //1 '*****如果？左边的表达式布尔为false就返回我******'
// 三目运算是可以嵌套的，只是不好阅读，如下
var ttt = true?true?1:2:0
console.log(ttt)


// ---------------------------------------------------------------------------------------------------------------------
/**
 * 内置函数
 * Object,Array,Boolean,Number,String,Function,Date,RegExp,Error,Math
 * instanceof判断一个函数是否是一个变量的构造函数
 */
console.log([] instanceof Array);  // true
console.log([] instanceof Object);  // true
console.log(1 instanceof Array);    // false
console.log('1' instanceof Object);  // false
console.log(1 instanceof Number);    // false
console.log('1' instanceof String);  // false